; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
;
; Super FX assembler emulator code
; (c) Copyright 1998, 1999 zsKnight and _Demo_.
;
; Permission to use, copy, modify and distribute Snes9x in both binary and
; source form, for non-commercial purposes, is hereby granted without fee,
; providing that this license information and copyright notice appear with
; all copies and any derived work.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event shall the authors be held liable for any damages
; arising from the use of this software.
;
; Snes9x is freeware for PERSONAL USE only. Commercial users should
; seek permission of the copyright holders first. Commercial use includes
; charging money for Snes9x or software derived from Snes9x.
;
; The copyright holders request that bug fixes and improvements to the code
; should be forwarded to them so everyone can benefit from the modifications
; in future versions.
;
; Super NES and Super Nintendo Entertainment System are trademarks of
; Nintendo Co., Limited and its subsidiary companies.
;
; ZSNES SuperFX emulation code and wrappers
; (C) Copyright 1997-8 zsKnight and _Demo_

; Used with the kind permission of the copyright holders.
;

%include "i386/macros.mac"

EXTSYM SfxR1,SfxR2,InitFxTables,SfxSFR,SfxSCMR,initsfxregsw,initsfxregsr
EXTSYM SfxPBR,SfxSCMR,NumberOfOpcodes,SfxCLSR,MainLoop,SfxCROM
EXTSYM SfxRomBuffer,SfxRAMMem,SfxLastRamAdr,SfxR0
EXTSYM PHnum2writesfxreg, SfxCPB, SfxROMBR, SfxRAMBR, SfxnRamBanks
EXTSYM SfxSignZero

[BITS 32]
SECTION .data

NEWSYM flagnz,   dd 0
NEWSYM romdata,  dd 0              ; rom data  (4MB = 4194304)

NEWSYM regptr, dd 0              ; pointer to registers
NEWSYM regptw,  dd 0              ; pointer to registers
NEWSYM regptra, times 49152 db 0
NEWSYM regptwa, times 49152 db 0

NEWSYM debstop, db 0
NEWSYM sfxramdata, dd 0              ; SuperFX Ram Data
NEWSYM sfxplottable, dd 0
NEWSYM FxTable, times 256 dd 0
NEWSYM FxTableA1, times 256 dd 0
NEWSYM FxTableA2, times 256 dd 0
NEWSYM FxTableA3, times 256 dd 0
NEWSYM FxTableb, times 256 dd 0
NEWSYM FxTablebA1, times 256 dd 0
NEWSYM FxTablebA2, times 256 dd 0
NEWSYM FxTablebA3, times 256 dd 0
NEWSYM FxTablec, times 256 dd 0
NEWSYM FxTablecA1, times 256 dd 0
NEWSYM FxTablecA2, times 256 dd 0
NEWSYM FxTablecA3, times 256 dd 0
NEWSYM FxTabled, times 256 dd 0
NEWSYM FxTabledA1, times 256 dd 0
NEWSYM FxTabledA2, times 256 dd 0
NEWSYM FxTabledA3, times 256 dd 0
NEWSYM SfxMemTable, times 256 dd 0
NEWSYM fxxand,  times 256 dd 0
NEWSYM fxbit01, times 256 dd 0
NEWSYM fxbit23, times 256 dd 0
NEWSYM fxbit45, times 256 dd 0
NEWSYM fxbit67, times 256 dd 0
NEWSYM PLOTJmpa, times 64 dd 0
NEWSYM PLOTJmpb, times 64 dd 0

NEWSYM NumberOfOpcodes2, dd 350
NEWSYM SFXCounter, dd 0
NEWSYM SfxAC, dd 0

;%INCLUDE "i386/fxtable.asm"
;%INCLUDE "i386/sfxproc.asm"
;%INCLUDE "i386/fxemu2.asm"
;%INCLUDE "i386/fxemu2b.asm"
;%INCLUDE "i386/fxemu2c.asm"

;
; Snes9x wrapper functions for the zsnes SuperFX code
; (C) Copyright 1998 Gary Henderson

SECTION .data

%ifdef __DJGPP__
%define SRAM _SRAM
%define ROM _ROM
%define RegRAM _RegRAM
%define S9xResetSuperFX _S9xResetSuperFX
%define S9xSuperFXWriteReg _S9xSuperFXWriteReg
%define S9xSuperFXReadReg _S9xSuperFXReadReg
%define S9xSuperFXExec _S9xSuperFXExec
%define S9xSuperFXPreSaveState _S9xSuperFXPreSaveState
%define S9xSuperFXPostSaveState _S9xSuperFXPostSaveState
%define S9xSuperFXPostLoadState _S9xSuperFXPostLoadState
%define SFXPlotTable _SFXPlotTable
%define WinterGold _WinterGold
%endif

EXTERN SRAM
EXTERN ROM
EXTERN RegRAM
EXTERN SFXPlotTable
EXTERN WinterGold

SECTION .text

GLOBAL S9xResetSuperFX
GLOBAL S9xSuperFXWriteReg
GLOBAL S9xSuperFXReadReg
GLOBAL S9xSuperFXExec
GLOBAL S9xSuperFXPreSaveState
GLOBAL S9xSuperFXPostSaveState
GLOBAL S9xSuperFXPostLoadState
GLOBAL StartSFX

StartSFX:
StartSFXret:
	jmp S9xSuperFXExec

S9xResetSuperFX:
	push ebx
	push esi
	push edi
	push ebp

	mov dword[SfxR1],0
	mov dword[SfxR2],0
	mov dword[SfxSignZero],1	; clear z flag

	mov eax,dword[SRAM]
	mov dword[sfxramdata],eax
	mov eax,dword[ROM]
	mov dword[romdata],eax
	mov eax,dword[SFXPlotTable]
	mov dword[sfxplottable],eax

	call InitFxTables

	mov dword[SfxSFR],0
	mov byte[SfxSCMR],0
	mov dword[regptr],regptra
	sub dword[regptr],8000h   ; Since register address starts @ 2000h
	mov dword[regptw],regptwa
	sub dword[regptw],8000h   ; Since register address starts @ 2000h
	call initsfxregsw
	call initsfxregsr

NEWSYM preparesfx
	mov byte[SFXCounter],0
	mov esi,[romdata]
	add esi,07FC0h
	cmp dword[esi],'FX S'
    	je .yessfxcounter
    	cmp dword[esi],'Stun'
    	jne .nosfxcounter
.yessfxcounter
	mov byte[SFXCounter],1
.nosfxcounter

    	; make table
    	mov byte[SfxAC],0
    	mov eax,[romdata]
    	cmp dword[eax+02B80h],0AB6CAB6Ch
    	jne .noac
    	mov byte[SfxAC],1
.noac
	call UpdateSFX

	pop ebp
	pop edi
	pop esi
	pop ebx
	ret

S9xSuperFXWriteReg:
	mov eax,dword[esp+4]
	mov ecx,dword[esp+8]
	push ebx
	push esi
	push edi
	push ebp
	test dword[regptwa+ecx*4-8000h], ~0
	jz .skipwrite
	call dword[regptwa+ecx*4-8000h]
.skipwrite:
	pop ebp
	pop edi
	pop esi
	pop ebx
	ret

S9xSuperFXReadReg:
	mov ecx,dword[esp+4]
	push ebx
	push esi
	push edi
	push ebp
	test dword[regptra+ecx*4-8000h], ~0
	jz .skipread
	call dword[regptra+ecx*4-8000h]
.skipread:
	pop ebp
	pop edi
	pop esi
	pop ebx
	and eax, 255
endfx:
	ret

EXTSYM SfxPBR,SCBRrel,SfxSCBR,SfxCOLR,SfxPOR
EXTSYM sfx128lineloc,sfx160lineloc,sfx192lineloc,sfxobjlineloc,sfxclineloc
EXTSYM fxbit01pcal,fxbit23pcal,fxbit45pcal,fxbit67pcal
S9xSuperFXExec:
    test byte[SfxSFR],20h
    jz endfx

    push ebx
    push esi
    push edi
    push ebp

    xor ebx,ebx
    mov bl,[SfxPBR]
    mov al,[SfxSCMR]
    and bl,7Fh
    cmp bl,70h
    jae .ram
    test al,10h
    jz .noaccess
    jmp .noram
.ram
    test al,08h
    jz .noaccess
.noram
    mov eax,[NumberOfOpcodes2]
    mov [NumberOfOpcodes],eax
    call MainLoop
.noaccess
    pop ebp
    pop edi
    pop esi
    pop edx
    ret

S9xSuperFXPreSaveState:
    mov ecx,dword[SfxCROM]
    sub dword[SfxRomBuffer],ecx
    mov ecx,dword[SfxRAMMem]
    sub dword[SfxLastRamAdr],ecx
; Copy num2writesfxreg bytes from SfxR0 to a free area in RegRAM.
    push ebx
    mov ecx,SfxR0
    mov edx,dword[RegRAM]
    add edx,7000h
    mov ebx,[PHnum2writesfxreg]
.loop
    mov al,[ecx]
    mov [edx],al
    inc ecx
    inc edx
    dec ebx
    jnz .loop
    pop ebx
    mov ecx,dword[SfxCROM]
    add dword[SfxRomBuffer],ecx
    mov ecx,dword[SfxRAMMem]
    add dword[SfxLastRamAdr],ecx
    ret

S9xSuperFXPostSaveState:
    ret

S9xSuperFXPostLoadState:
; Copy num2writesfxreg bytes from a free area in RegRAM to SfxR0
    push ebx
    mov ecx,SfxR0
    mov edx,dword[RegRAM]
    add edx,7000h
    mov ebx,[PHnum2writesfxreg]
.loop
    mov al,[edx]
    mov [ecx],al
    inc ecx
    inc edx
    dec ebx
    jnz .loop
    pop ebx
    xor ecx,ecx
    mov cl,byte[SfxPBR]
    mov ecx,dword[SfxMemTable+ecx*4]
    mov dword[SfxCPB],ecx

    xor ecx,ecx
    mov cl,byte[SfxROMBR]
    mov ecx,dword[SfxMemTable+ecx*4]
    mov dword[SfxCROM],ecx

    xor ecx,ecx
    mov cl,byte[SfxRAMBR]
    shl ecx,16
    add ecx,dword[sfxramdata]
    mov dword [SfxRAMMem],ecx

    mov ecx,dword[SfxCROM]
    add dword[SfxRomBuffer],ecx
    mov ecx,dword[SfxRAMMem]
    add dword[SfxLastRamAdr],ecx
; Fix for mystery zeroing of SfxnRamBanks, allowing junk RAMBR values to be
; set in turn causing a crash when the code tries to access the junk RAM bank.
    mov dword [SfxnRamBanks], 4
    call UpdateSFX
    ret

NEWSYM UpdatePORSCMR
   push ebx
   push eax
   test byte[SfxPOR],10h
   jnz .objmode
   mov al,[SfxSCMR]
   and al,00100100b     ; 4 + 32
   cmp al,4
   je .lines160
   cmp al,32
   je .lines192
   cmp al,36
   je .objmode
   mov eax,[sfx128lineloc]
   jmp .donelines
.lines160
   mov eax,[sfx160lineloc]
   jmp .donelines
.lines192
   mov eax,[sfx192lineloc]
   jmp .donelines
.objmode
   mov eax,[sfxobjlineloc]
.donelines
   mov [sfxclineloc],eax

   mov al,[SfxSCMR]
   and eax,00000011b
   mov bl,[SfxPOR]
   and bl,0Fh
   shl bl,2
   or al,bl
   mov ebx,[PLOTJmpb+eax*4]
   mov eax,[PLOTJmpa+eax*4]
   mov dword [FxTable+4Ch*4],eax
   mov dword [FxTableb+4Ch*4],eax
   mov dword [FxTablec+4Ch*4],eax
   mov dword [FxTabled+4Ch*4],ebx
   pop eax
   pop ebx
   ret

NEWSYM UpdateSCBRCOLR
   push eax
   push ebx
   mov ebx,[SfxSCBR]
   shl ebx,10
   add ebx,[sfxramdata]
   mov [SCBRrel],ebx
   mov eax,[SfxCOLR]
   mov ebx,[fxbit01+eax*4]
   mov [fxbit01pcal],ebx
   mov ebx,[fxbit23+eax*4]
   mov [fxbit23pcal],ebx
   mov ebx,[fxbit45+eax*4]
   mov [fxbit45pcal],ebx
   mov ebx,[fxbit67+eax*4]
   mov [fxbit67pcal],ebx
   pop ebx
   pop eax
   ret

NEWSYM UpdateCLSR
   mov dword [NumberOfOpcodes2],350 ; 0FFFFFFFh;350
   test byte[SfxCLSR],01h
   jz .nohighsfx
   mov dword [NumberOfOpcodes2],700 ;700
.nohighsfx
    cmp byte[SFXCounter],1
    je .noyi
    mov dword [NumberOfOpcodes2],0FFFFFFFh
.noyi
   ret

NEWSYM UpdateSFX
   call UpdatePORSCMR
   call UpdatePORSCMR
   call UpdateCLSR
   ret
